#pragma once
#include "typedefs.h"
#include "DraftFwd.h"

class QFile;

class Draft
{
    friend class Machine;

private:
    Draft();

public:
    static DraftPtr FromFile(QFile* file);
    static DraftPtr FromString(const QString& string);
    static DraftPtr Default();

public:
    bool isValid();
    QString GetValidationErrors(const QString& separator = "\n");

public:
    bool OnTag(const QString& tag, const StringMap& attrPairs, bool passUnknown = true); 

public:
    const StringMapMap& Channels() const;
    static QString LastError();

private:
    static DraftPtr GetDraft(QIODevice* io);
    
private:
    bool AddProcedure(const StringMap& tuple);
    bool AddTransfer(const StringMap& tuple);
    bool SetInitial(const StringMap& tuple);
    bool AddAction(const StringMap& tuple);
    bool AddGlobal(const StringMap& tuple);
    bool AddState(const StringMap& tuple);
    bool AddChar(const StringMap& tuple);

private:
    bool AddChannel(const StringMap& tuple);
    bool AddProperty(const StringMap& tuple);

private:
    void RegisterHandlers();
    void DrawMinimal();

private:
    void CheckTransfersDest();
    void CheckInitialExist();
    void CheckSendChannels();

private:
    void RegisterChannel();
    void RegisterCommon();

private:
    static void SetError(const QString& error);

private:
    StringMap           globals;
    
    StringMapListMap    state2procedures;
    StringListMap       state2transfers;
    
    StringMap           transfer2state;
    StringListMap       transfer2char;
    StringMapListMap    transfer2actions;

    StringMapMap        channels;

private:
    QString             channel;
    QString             initialState;
    QString             currentState;
    QString             transferUID;
    int                 transferNum;

private:
    static QString      lastError;
    QStringList         validationErrorList;

private:
    typedef bool (Draft::*TagHandler)(const StringMap&); 
    QMap<QString, TagHandler> _tagHandlers;
};